package com.seguriapp.controller;

import static com.google.common.collect.Lists.newArrayList;

import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import net.sf.json.JSONException;
import net.sf.json.JSONObject;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import com.seguriapp.entities.Complaint;
import com.seguriapp.entities.CrimeCategory;
import com.seguriapp.services.ComplaintService;
import com.seguriapp.util.CriminalItem;
import com.seguriapp.util.Util;

/**
 * Represents the controller for the criminal activity entity
 * 
 * @author Tania Gonzales(taniadgv@gmail.com)
 */
@Controller
@RequestMapping("/criminalActivity")
public class CriminalActivityController {

  private static final Logger LOGGER = Logger.getLogger(CriminalActivityController.class);

  @Autowired
  private ComplaintService complaintService;

  @RequestMapping(value = "/getCriminalActivityMap", method = RequestMethod.GET)
  @ResponseBody()
  public String getCriminalActivityMap(final HttpServletRequest request) {
    final List<CriminalItem> criminalMap = complaintService.getCriminalActivityMap(Double.parseDouble(request.getParameter("long")),
        Double.parseDouble(request.getParameter("lat")));
    final List<Map<?, ?>> l1 = new LinkedList<Map<?, ?>>();
    for (CriminalItem criminalItem : criminalMap) {
      l1.add(criminalItem.toJsonString());
    }
    JSONObject obj = new JSONObject();
    try {
      obj.put("geonames", l1);
    } catch (JSONException e) {
      LOGGER.error("Error getting Criminal Activity Map", e);
    }
    return obj.toString();
  }

  @RequestMapping(value = "/getCriminalActivityMapItems", method = RequestMethod.POST)
  @ResponseBody()
  public String getCriminalActivityMapV1(final @RequestBody String mapOptionsJs) {
    final List<CriminalItem> criminalMap = getCriminalActivityMapDataV1(mapOptionsJs);
    if (criminalMap != null) {
      LOGGER.info("Size of criminal map : " + criminalMap.size());
      final String response = Util.parseEntityListToJson("criminalItems", criminalMap);
      return response;
    }
    return StringUtils.EMPTY;
  }

  @RequestMapping(value = "/getCriminalActivityMap", method = RequestMethod.POST)
  @ResponseBody()
  public String getCriminalActivityMap(final @RequestBody String mapOptionsJs) {
    final List<Complaint> criminalMap = getCriminalActivityMapData(mapOptionsJs);
    if (criminalMap != null) {
      LOGGER.info("Size of criminal map : " + criminalMap.size());
      final String response = Util.parseEntityListToJson("complaints", criminalMap);
      return response;
    }
    return StringUtils.EMPTY;
  }

  @RequestMapping(value = "/getCrimeCategoryList", method = RequestMethod.GET)
  @ResponseBody()
  public String getCrimeCategoryList() {
    final List<CrimeCategory> crimeCategoryList = complaintService.getCrimeCategoryList();
    return Util.parseEntityListToJson("crimeCategoryList", crimeCategoryList);
  }

  private List<CriminalItem> getCriminalActivityMapDataV1(final String mapInfoJs) {
    LOGGER.info("Request for Criminal Activity Map: " + mapInfoJs);
    if (mapInfoJs == null || mapInfoJs.isEmpty()) {
      return null;
    }
    final JSONObject root = JSONObject.fromObject(mapInfoJs);
    if (root.has("mapOptions") && root.has("zoomLevel") && root.has("deviceType")) {
      final String mapOptions = root.getString("mapOptions");
      if (mapOptions == null || mapOptions.isEmpty()) {
        return null;
      }
      final int zoomLevel = root.getInt("zoomLevel");
      final int deviceType = root.getInt("deviceType");
      final List<Long> crimeCategories = newArrayList();
      final String[] crimeCategoriesStr = mapOptions.split(Util.SEPARATOR);
      for (final String crimeCategoryStr : crimeCategoriesStr) {
        crimeCategories.add(Long.valueOf(crimeCategoryStr));
      }
      if (crimeCategories.isEmpty()) {
        return null;
      }
      final int allResults = root.has("allResults") ? root.getInt("allResults") : 0;
      return complaintService.getCriminalActivityMap(crimeCategories, zoomLevel, deviceType, allResults);
    }
    return null;
  }

  private List<Complaint> getCriminalActivityMapData(final String mapInfoJs) {
    LOGGER.info("Request for Criminal Activity Map: " + mapInfoJs);
    if (mapInfoJs == null || mapInfoJs.isEmpty()) {
      return null;
    }
    final JSONObject root = JSONObject.fromObject(mapInfoJs);
    if (root.has("mapOptions")) {
      final String mapOptions = root.getString("mapOptions");
      if (mapOptions == null || mapOptions.isEmpty()) {
        return null;
      }
      final List<Long> crimeCategories = newArrayList();
      final String[] crimeCategoriesStr = mapOptions.split(Util.SEPARATOR);
      for (final String crimeCategoryStr : crimeCategoriesStr) {
        crimeCategories.add(Long.valueOf(crimeCategoryStr));
      }
      if (crimeCategories.isEmpty()) {
        return null;
      }
      return complaintService.getCriminalActivityMap(crimeCategories);
    }
    return null;
  }

}
